import java.io.Serializable;
import java.util.Random;


// implements the base class for factors that need to be multiplied, diffed, matched, etc.
public class PLFactor implements Serializable {
	private static final long serialVersionUID = 1L;

	protected Random mGenerator = new Random();

	protected PLDist mDist = new PLDist(); 
	protected float[] mValSet = null;
	
	public PLFactor(float[] valSet) { 
		mValSet = valSet;
		// set the default distribution 
		mDist.SetDefaultDistribution(valSet.length);
	}

	public float[] GetValSet() {return mValSet;}
	public void SetValSet(float[] valSet) {mValSet = valSet;}
	
	public PLDist GetDist() {return mDist;}
	public void SetDist(PLDist dist) {mDist = dist;}

	public float GetAValue() {
		int index = mDist.PickIndex();

		float start = index > 0 ? mValSet[index -1] : 0;
		float end = mValSet[index];
		return start + mGenerator.nextFloat() * (end - start);	
	}

	// give a new value, updates the distribution 
	public void Update(float value) {	
		int index = -1;
		if (value > mValSet[mValSet.length-1]) {
			index = mValSet.length-1;
		} else {
		 	index  = PLUtil.find_first_greater_than(mValSet, value);
		}		 
		PLLearnUtils.UpdateDistForWinner(mDist, index);		
	}	


	public static float[] GetDefaultRatioSet() {
		final float[] valSet = {0.25f, 0.5f, 0.75f, 1, 1.25f, 1.5f, 1.75f, 2, 3, 4, 6, 8, 10, 10};
		return valSet;	
	}

	public static float[] GetDefaultDistanceDeltaSet() {
		final float[] valSet = {1, 10, 25, 40, 60, 85, 110, 140, 180, 250, 
								300, 350, 410, 470, 540, 610, 700, 800, 900, 1000, 1000};
		return valSet;	
	}

	public static float[] GetDefaultPiDeltaSet() {
		final float[] valSet = {(float) (Math.PI/8), (float) (2*Math.PI/8), (float) (3*Math.PI/8), (float) (4*Math.PI/8), 
								(float) (5*Math.PI/8), (float) (6*Math.PI/8), (float) (7*Math.PI/8), (float) Math.PI, 
								(float) (9*Math.PI/8), (float) (10*Math.PI/8), (float) (11*Math.PI/8), (float) (12*Math.PI/8), 
								(float) (13*Math.PI/8), (float) (14*Math.PI/8), (float) (15*Math.PI/8), (float) (2*Math.PI)} ;
		return valSet;	
	}

	public static float[] GetDefaultQuadrantSet() {
		final float[] valSet = {0, 1, 2, 3} ;
		return valSet;	
	}
	
}
